/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package multimedia;

import MVC.IController;
import gui.multimedia.MultimediaView;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import javax.sound.sampled.UnsupportedAudioFileException;
import technical.ClInit;

/**
 *
 * @author thomas
 */
public class MultimediaController implements IController {

    private static MultimediaController __instance = null;
    private MultimediaView _myView;
    private MultimediaModel _myModel;
    
    private AudioPlaylistController _defaultPlaylist = createUnnamedPlaylist();
    private AudioPlaylistController _activePlaylist = new AudioPlaylistController();
    private ArrayList<AudioPlaylistController> _playlists = new ArrayList<AudioPlaylistController>();
    
    private static String __musicDirectory = ClInit.getMusicFolder();

    /**
     * @return the __musicDirectory
     */
    public static String getMusicDirectory() {
        return __musicDirectory;
    }

    /**
     * @param aMusicDirectory the __musicDirectory to set
     */
    public static void setMusicDirectory(String aMusicDirectory) {
        __musicDirectory = aMusicDirectory;
    }
    
    public static ArrayList<String> getSupportedExtensions() {
        ArrayList<String> ext = new ArrayList<String>();
        ext.add(".mp3");
        ext.add(".ogg");
        return ext;
    }
    
    /**
     * Try if the extension path match with supported extension
     * @param path
     * @return True if extension is correct, else false
     */
    public static boolean checkExtension(String path) {
        for (String ext : getSupportedExtensions()) {
            if (path.endsWith(ext)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Create a Multimedia controller
     * It initialise model and load playlists
     */
    private MultimediaController() {
        _myModel = new MultimediaModel();
        loadPlaylists();
    }

    /**
     * Create a Multimedia controller
     * It initialise model load playlists and link the associated view
     * @param myView It is the associated view
     */
    private MultimediaController(MultimediaView myView) {
        this();
        _myView = myView;
    }

    /**
     * Method to do a singleton initalised with a view
     * @param myView
     * @return Unique instance of MultimediaController
     */
    public static MultimediaController getInstance(MultimediaView myView) throws FileNotFoundException {
        if (__instance == null) {
            
            
            if (!new File(__musicDirectory).isDirectory()) {
                throw new FileNotFoundException();
            }

            __instance = new MultimediaController(myView);
        }
        return __instance;
    }

    /**
     * @return the _myModel
     */
    public MultimediaModel getModel() {
        return getModel(true);
    }
    
    public MultimediaModel getModel(boolean update) {
        if (update) {
            updateModel();
        }
        return _myModel;
    }

    /**
     * @param myModel the _myModel to set
     */
    public void setModel(MultimediaModel myModel) {
        this._myModel = myModel;
    }
    
    /**
     * Update the current model
     */
    public void updateModel() {
        if (checkActivePlaylist()) {
            _myModel.updateModel(_activePlaylist.getModel());
        }
    }

    /**
     * Create a new playlist nammed "Sans titre"
     * @return an empty AudioPlaylistController
     */
    private AudioPlaylistController createUnnamedPlaylist() {
        AudioPlaylistController pl = new AudioPlaylistController();
        pl.getModel().setName("Sans titre");
        return pl;
    }

    /**
     * @return the active playList
     */
    public AudioPlaylistController getActivePlaylist() {
        return _activePlaylist;
    }

    /**
     * @return all playLists
     */
    public ArrayList<AudioPlaylistController> getPlaylists() {
        return _playlists;
    }

    /**
     * Add a song to the active playlist
     * @param path Path of the song to add
     * @throws FileNotFoundException            If file is not found
     * @throws IOException                      If error when file is reading
     * @throws UnsupportedAudioFileException    If extension is not supported by reader
     */
    public void addSongToActivePlaylist(String path) throws FileNotFoundException, IOException, UnsupportedAudioFileException {
        _activePlaylist.addSong(path);
    }

    /**
     * Load all the playlists or create an empty if it was no playlist
     * TODO : Ajouter le chargement de playlist déjà crée
     */
    public final void loadPlaylists() {
        if (_playlists.isEmpty()) {
            System.out.println("Ajout playlist vide");
            _playlists.add(_defaultPlaylist);
        }

        _activePlaylist = _playlists.get(0);
    }

    /**
     * Load a playlist
     * @param newPlayList 
     */
    private void loadPlaylist(AudioPlaylistController newPlayList) {
    }

    /**
     * Check if playlist is correct or not
     * Test if array list of songs is empty
     * @return true if correct or false
     */
    public boolean checkActivePlaylist() {
        return _activePlaylist != null && _activePlaylist.checkPlaylist();
    }

    /**
     * 
     * @param path
     * @throws FileNotFoundException            If file is not found
     * @throws IOException                      If error when file is reading
     * @throws UnsupportedAudioFileException    If extension is not supported by reader
     */
    public void listenToSong(String path) throws FileNotFoundException, IOException, UnsupportedAudioFileException {

        if (_activePlaylist != null) {
            _activePlaylist.stop();
            _activePlaylist = null;
        }

        _activePlaylist = createUnnamedPlaylist();
        addSongToActivePlaylist(path);
        play();
    }

    /**
     * Play the active song or the first song in the playlist if playlist is correct
     */
    public void play() {
        if (!checkActivePlaylist()) {
            return;
        }

        _activePlaylist.play();
        _myModel.setState("play");
    }

    /**
     * Toogle to pause the active song if playlist is correct
     */
    public void pause() {
        if (!checkActivePlaylist()) {
            return;
        }

        _activePlaylist.pause();
        _myModel.setState("pause");
    }

    /**
     * Restart the song or if song is not begin start the previous
     */
    public void previous() throws UnsupportedAudioFileException, IOException {
        if (!checkActivePlaylist()) {
            return;
        }

        _activePlaylist.previous();
    }

    /**
     * Start the next song if exist or stop anything
     * TODO Prévoir un mode aléatoire qui ne choisit pas la prochaine chanson de la liste
     */
    public void next() throws UnsupportedAudioFileException, IOException {
        if (!checkActivePlaylist()) {
            return;
        }

        _activePlaylist.next();
    }

    /**
     * Unload the active song if exist and set to null concerned variable if playlist is correct
     */
    public void stop() {
        if (!checkActivePlaylist()) {
            return;
        }
        
        _activePlaylist.stop();
           
        _myModel.setState("stop");
        _myView.reinitializeToolBar();
    }
    
    public void setShuffle(boolean shuffle) {
        if (checkActivePlaylist()) {
            _activePlaylist.isShuffle(shuffle);
        }
        _myModel.isShuffle(shuffle);
    }
    
    public void setRepeat(boolean repeat) {
        if (checkActivePlaylist()) {
            _activePlaylist.isRepeat(repeat);
        }
        _myModel.isRepeat(repeat);
    }

    public String timeToString(int duration) {

        String result = "";

        int hour = 0;
        hour = duration / 3600;
        if (hour > 1) {
            result += String.valueOf(hour) + ":";
            duration = duration % 3600;
        }

        result += new DecimalFormat("00").format(duration / 60) + ":";
        duration = duration % 60;

        result += new DecimalFormat("00").format(duration);

        return result;
    }
}
